package khh;

import java.awt.Color;
import robocode.BulletHitEvent;
import robocode.HitByBulletEvent;
import robocode.HitRobotEvent;
import robocode.Robot;
import robocode.ScannedRobotEvent;
import robocode.WinEvent;

/**
 * This robot is created with the intention of defeating several sample robots that were included
 * with the robocode download. For movement it uses the properties of the wall robot sample moving
 * around the battlefield along the walls, for tracking it uses the code from Boom04, and for firing
 * it uses the principles from Boom03 (firing at different powers based on distance to enemy robot).
 * 
 * @author Kylan Hughes
 * @version 1.0
 */

public class Kylan extends Robot {
  // Firedelay allows the robot to move more instead of sitting still and shooting.
  int firedelay = 0;
  // The enemy robots angle on backfield.
  double enemyrobot;
  // The distance the robot is going to move.
  double moving;
  // The distance the enemy robot is away from the robot.
  double distance;
  // Angle to turn after being hit by a bullet.
  double movebullet = 90;
  // Keeps track if robot should change directions after being hit.
  double changedirection = 0;

  /**
   * The main method for running the robot. Gets overriden when any event occurs.
   */
  public void run() {
    setBodyColor(Color.black);
    setGunColor(Color.white);
    setRadarColor(Color.white);
    // This code largely draws from the sample robot walls that was included with the
    // robocode package. It initially makes the robot move to the nearest wall and
    // then move around the battlefield in a clockwise direction.
    moving = Math.max(getBattleFieldWidth(), getBattleFieldHeight());
    turnLeft(getHeading() % 90);
    if (getHeading() == 0) {
      turnLeft(90);
    }
    else if (getHeading() == 90) {
      turnLeft(180);
    }
    else if (getHeading() == 180) {
      turnRight(90);
    }
    ahead(moving);
    while (true) {
      turnRight(movebullet);
      turnRadarRight(360);
      ahead(moving);
      if (firedelay == 0) {
        turnGunRight(360);
        firedelay = 1;
      }
      else {
        firedelay = 0;
      }
    }
  }

  /**
   * This methods code is for populating the variables that other methods use and for tracking and
   * firing at the enemy robot.
   * 
   * @param e is the first robot that the robot encounters.
   */
  public void onScannedRobot(ScannedRobotEvent e) {
    distance = e.getDistance();
    // sets the enemy tanks angle to be dependent on the battlefield instead of on your position.
    // makes it easier to determine where to turn the gun.
    enemyrobot = (getHeading() + e.getBearing()) % 360;
    turnGunRight(trackEnemyRobot(getGunHeading() % 360, enemyrobot));
    fire(firePower(distance));
  }

  /**
   * If the enemy is far away use a bullet that will hurt you less because you have a higher
   * probability of missing.
   * @param dist is the distance between Kylan and the scanned enemy robot.
   * @return int - 1, 2, or 3 based on the distance of the enemy tank.
   */
  public static int firePower(double dist) {
    // the distance is less than 100 so use power 3
    if (dist <= 100) {
      return 3;
      // distance is in between 100 and 500 so use power 2
    }
    else if ((dist > 100) && (dist <= 500)) {
      return 2;
      // enemy is far away so use power 1
    }
    else {
      return 1;
    }
  }

  /**
   * Code taken from Boom04 that points the gun of the robot at the enemy robot.
   * @param gun is the heading of the gun in degrees.
   * @param enemy is the heading of the enemy robot in relation to Kylan.
   * @return the degrees the gun should turn so that it is facing towards the enemy.
   */
  public static double trackEnemyRobot(double gun, double enemy) {
    double gunHeading = gun % 360;
    double enemyHeading = enemy % 360;
    if (enemyHeading >= gunHeading) {
      // The enemy robot is more to the left of the gun than to the right
      if ((enemyHeading - gunHeading) > 180) {
        // move the gun to the left.
        return (-(gunHeading) - (360 - enemyHeading));
        // if (firedelay == 0) {
        // fire(firePower(distance));
        // turnGunRight(360);
        // firedelay = 1;
        // }
        // else {
        // firedelay = 0;
        // }
      }
      else {
        // The enemy robot is more to the right of the gun so move gun to the right.
        return (enemyHeading - gunHeading);
        // if (firedelay == 0) {
        // fire(firePower(distance));
        // turnGunRight(360);
        // firedelay = 1;
        // }
        // else {
        // firedelay = 0;
        // }
      }
    }
    else {
      // The gun is more to the left of the enemy robot
      if ((gunHeading - enemyHeading) > 180) {
        // move the gun to the right
        return ((360 - gunHeading) + enemyHeading);
        // if (firedelay == 0) {
        // fire(firePower(distance));
        // turnGunRight(360);
        // firedelay = 1;
        // }
        // else {
        // firedelay = 0;
        // }
      }
      else {
        // The gun is more to the right of the enemy robot so move the gun left.
        return (enemyHeading - gunHeading);
        // fire(firePower(distance));
      }
    }
  }

  /**
   * Turn around and go the other way if hit. Since probability of being hit is greater when closer
   * to enemy this attempts to have the robot go in other direction of enemy robot.
   * 
   * @param e contains information about where the bullet came from, allows this method to override
   * all other actions.
   */
  public void onHitByBullet(HitByBulletEvent e) {
    setBodyColor(Color.black);
    setGunColor(Color.red);
    setRadarColor(Color.red);
    // Going around the room clockwise.
    if (movebullet == 90) {
      if (changedirection == 0) {
        // Change it so going counter-clockwise.
        movebullet = -90;
        turnRight(180);
        ahead(moving);
        turnRadarRight(360);
        turnGunRight(trackEnemyRobot(getGunHeading() % 360, enemyrobot));
        fire(firePower(distance));
        changedirection = 1;
      }
      else {
        changedirection = 0;
      }
      // Going around the room counter-clockwise.
    }
    else {
      if (changedirection == 0) {
        // Change it so going clockwise.
        movebullet = 90;
        turnRight(180);
        ahead(moving);
        turnRadarRight(360);
        turnGunRight(trackEnemyRobot(getGunHeading() % 360, enemyrobot));
        fire(firePower(distance));
        changedirection = 1;
      }
      else {
        changedirection = 0;
      }
    }
  }

  /**
   * When hit by a bullet change the color of the robot.
   * 
   * @param e holds information about what happens when your bullet hits another robot.
   */
  public void onBulletHit(BulletHitEvent e) {
    setBodyColor(Color.black);
    setGunColor(Color.blue);
    setRadarColor(Color.blue);
  }

  /**
   * When collide with a robot reverse direction around the field.
   * 
   * @param e holds information about the robot you hit.
   */
  public void onHitRobot(HitRobotEvent e) {
    turnRight(180);
    ahead(moving);
    movebullet = -movebullet;
  }

  /**
   * Called if Kylan robot is the winner.
   * 
   * @param e holds information about your win.
   */
  public void onWin(WinEvent e) {
    setBodyColor(Color.green);
    setGunColor(Color.green);
    setRadarColor(Color.green);
    while (true) {
      turnLeft(15);
      turnRight(15);
    }
  }
}
